home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / EXAMPLES / IDRAW / PAGE.C < prev    next >
C/C++ Source or Header  |  1991-12-20  |  10KB  |  324 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. // $Header: page.c,v 1.9 90/01/25 16:27:23 interran Exp $
  24. // implements class Page.
  25.  
  26. #include "ipaint.h"
  27. #include "page.h"
  28. #include "slpict.h"
  29. #include <InterViews/Graphic/lines.h>
  30. #include <InterViews/Graphic/polygons.h>
  31. #include <InterViews/Graphic/util.h>
  32. #include <InterViews/canvas.h>
  33. #include <InterViews/painter.h>
  34. #include <InterViews/transformer.h>
  35.  
  36. // Page starts out with gravity disabled, spacing set to the default
  37. // value, visibility disabled, and an empty picture.
  38.  
  39. Page::Page (double w, double h, double b, Graphic* gs) : (gs) {
  40.     pagewidth = w;
  41.     pageheight = h;
  42.     pgwidth = round(w);
  43.     pgheight = round(h);
  44.     border = new PBrush(0xffff, round(b));
  45.     gravity = false;
  46.     spacing_pixels = 0.0;
  47.     spacing_points = 0.0;
  48.     visibility = false;
  49.     x = y = nil;
  50.     SetGridSpacing(GRID_DEFAULTSPACING);
  51.     grid_gs = new FullGraphic;
  52.     grid_tt = new Transformer;
  53.     grid_gs->SetBrush(psingle);
  54.     grid_gs->SetColors(pblack, pwhite);
  55.     grid_gs->SetPattern(psolid);
  56.     grid_gs->SetTransformer(grid_tt);
  57.     grid_gs->FillBg(true);
  58.     picture = nil;
  59.     SetPicture(nil);
  60.     if (GetTransformer() == nil) {
  61.     SetTransformer(new Transformer);
  62.     }
  63. }
  64.  
  65. Page::~Page () {
  66.     delete border;
  67.     delete x; 
  68.     delete y;
  69.     delete grid_gs;
  70. }
  71.  
  72. // GetBackgroundColor gets the background color for DrawingView.
  73.  
  74. Color* Page::GetBackgroundColor () {
  75.     PColor* bg = grid_gs->GetBgColor();
  76.     return *bg;
  77. }
  78.  
  79. // SetPicture replaces the old picture with a new picture (creating an
  80. // empty one if necessary) and deletes the old picture.
  81.  
  82. void Page::SetPicture (PictSelection* newpic) {
  83.     if (newpic == nil) {
  84.     newpic = new PictSelection;
  85.     }
  86.     if (picture != nil) {
  87.     Remove(picture);
  88.     delete picture;
  89.     }
  90.     picture = newpic;
  91.     Append(picture);
  92. }
  93.  
  94. // SetGridSpacing changes the spacing between the grid points, which
  95. // also requires reallocating the number of points in the grid.
  96.  
  97. void Page::SetGridSpacing (double p, boolean in_pixels) {
  98.     double old_spacing_pixels = spacing_pixels;
  99.  
  100.     if (in_pixels) {
  101.     spacing_points = p / points;
  102.     spacing_pixels = p;
  103.     } else {
  104.     spacing_points = p;
  105.     spacing_pixels = p * points;
  106.     }
  107.     if (spacing_pixels != old_spacing_pixels) {
  108.     delete x;
  109.     delete y;
  110.     int x_count = int(pagewidth/spacing_pixels) + 1;
  111.     int y_count = int(pageheight/spacing_pixels) + 1;
  112.     int count = x_count * y_count;
  113.     x = new Coord[count];
  114.     y = new Coord[count];
  115.     }
  116. }
  117.  
  118. // Center replaces the page's matrix with a freshly generated matrix
  119. // to center the page in the window and get rid of accumulated
  120. // roundoff errors.
  121.  
  122. void Page::Center (float mag, float wincx, float wincy) {
  123.     Transformer* t = GetTransformer();
  124.     float cx, cy;
  125.  
  126.     if (t->Rotated90()) {
  127.     *t = identity;
  128.     ToggleOrientation();
  129.     } else {
  130.     *t = identity;
  131.     }
  132.     GetCenter(cx, cy);
  133.     Scale(mag, mag, cx, cy);
  134.     Translate(wincx - cx, wincy - cy);
  135. }
  136.  
  137. // Constrain replaces the given point with the closest grid point if
  138. // gravity has been enabled.
  139.  
  140. void Page::Constrain (Coord& x, Coord& y) {
  141.     if (gravity) {
  142.     float x0, y0;
  143.     grid_tt->InvTransform(float(x), float(y), x0, y0);
  144.     x0 = round(round(x0/spacing_pixels) * spacing_pixels);
  145.     y0 = round(round(y0/spacing_pixels) * spacing_pixels);
  146.     grid_tt->Transform(x0, y0, x0, y0);
  147.     x = round(x0);
  148.     y = round(y0);
  149.     }
  150. }
  151.  
  152. // ToggleOrientation examines the picture's matrix to see what state
  153. // it is in and flips the matrix to the other state.
  154.  
  155. void Page::ToggleOrientation () {
  156.     Transformer* t = GetTransformer();
  157.     float l, b, dx, dy;
  158.  
  159.     if (t->Rotated90()) {
  160.     t->Transform(0.0, -pagewidth, dx, dy);
  161.     t->Transform(0.0, 0.0, l, b);
  162.     Translate(dx - l, dy - b);
  163.     Rotate(90.0, l, b);
  164.     } else {
  165.     t->Transform(0.0, 0.0, l, b);
  166.     t->Transform(0.0, pagewidth, dx, dy);
  167.     Rotate(-90.0, l, b);
  168.     Translate(dx - l, dy - b);
  169.     }
  170. }
  171.  
  172. // getExtent returns the page's dimensions as its extent instead of
  173. // returning the extent of its picture so idraw's panner will always
  174. // show the page's extent, not the picture's extent.
  175.  
  176. void Page::getExtent (float& l, float& b, float& cx, float& cy,
  177. float& tol, Graphic* gs) {
  178.     float dummy1, dummy2;
  179.     transformRect(0.0, 0.0, pagewidth, pageheight, l, b, dummy1, dummy2, gs);
  180.     transform(pagewidth/2, pageheight/2, cx, cy, gs);
  181.     tol = 0;
  182. }
  183.  
  184. // draw draws the grid, picture, and boundary.
  185.  
  186. void Page::draw (Canvas* c, Graphic* gs) {
  187.     concatTransformer(nil, gs->GetTransformer(), grid_tt);
  188.     drawGrid(c, grid_gs);
  189.     Picture::draw(c, gs);
  190.     drawBoundary(c, grid_gs);
  191. }
  192.  
  193. // drawGrid passes the work off to drawGridClipped.
  194.  
  195. void Page::drawGrid (Canvas* c, Graphic* gs) {
  196.     Coord xmax = c->Width();
  197.     Coord ymax = c->Height();
  198.     drawGridClipped(c, 0, 0, xmax, ymax, gs);
  199. }
  200.  
  201. // drawBoundary draws the boundary around the page.
  202.  
  203. void Page::drawBoundary (Canvas* c, Graphic* gs) {
  204.     gs->SetBrush(border);
  205.     update(gs);
  206.     pRect(c, 0, 0, pgwidth, pgheight);
  207. }
  208.  
  209. // drawClipped draws part of the grid, picture, and boundary.
  210.  
  211. void Page::drawClipped (
  212.     Canvas* c, Coord l, Coord b, Coord r, Coord t, Graphic* gs
  213. ) {
  214.     concatTransformer(nil, gs->GetTransformer(), grid_tt);
  215.     drawGridClipped(c, l, b, r, t, grid_gs);
  216.     drawPictureClipped(c, l, b, r, t, gs);
  217.     drawBoundaryClipped(c, l, b, r, t, grid_gs);
  218. }
  219.  
  220. // drawGridClipped grids the given area with points if visibility has
  221. // been enabled.  It sends the points in chunks of MAXCHUNK points
  222. // each because Xlib does not yet break up too-big requests.
  223.  
  224. void Page::drawGridClipped (Canvas* c, Coord l, Coord b, Coord r, Coord t,
  225. Graphic* gs) {
  226.     if (visibility) {
  227.     gs->SetBrush(psingle);
  228.     update(gs);
  229.     int ntotal = DefinePoints(l, b, r, t, gs);
  230.     int nsent = 0;
  231.     while (nsent < ntotal) {
  232.         const int MAXCHUNK = 6000;
  233.         int nchunk = min(MAXCHUNK, ntotal - nsent);
  234.         pMultiPoint(c, &x[nsent], &y[nsent], nchunk);
  235.         nsent += nchunk;
  236.     }
  237.     }
  238. }
  239.  
  240. // drawPictureClipped goes right ahead and draws the picture, letting
  241. // it decide if its extent intersects the clipping box.
  242.  
  243. void Page::drawPictureClipped (
  244.     Canvas* c, Coord l, Coord b, Coord r, Coord t, Graphic* gs
  245. ) {
  246.     register RefList* i;
  247.     Graphic* gr;
  248.     FullGraphic gstemp;
  249.     Transformer ttemp;
  250.     
  251.     gstemp.SetTransformer(&ttemp);
  252.     for (i = refList->First(); i != refList->End(); i = i->Next()) {
  253.     gr = getGraphic(i);
  254.     concatGraphic(gr, gr, gs, &gstemp);
  255.     drawClippedGraphic(gr, c, l, b, r, t, &gstemp);
  256.     }
  257.     gstemp.SetTransformer(nil); /* to avoid deleting ttemp explicitly */
  258. }
  259.  
  260. // drawBoundaryClipped draws part of the boundary around the page.
  261.  
  262. void Page::drawBoundaryClipped (
  263.     Canvas* c, Coord l, Coord b, Coord r, Coord t, Graphic* gs
  264. ) {
  265.     BoxObj clipBox(l, b, r, t);
  266.     
  267.     Coord x0, y0, x1, y1, x2, y2, x3, y3;
  268.     transform(0, 0, x0, y0, gs);
  269.     transform(0, pgheight, x1, y1, gs);
  270.     transform(pgwidth, 0, x2, y2, gs);
  271.     transform(pgwidth, pgheight, x3, y3, gs);
  272.     LineObj lLine(x0, y0, x1, y1);
  273.     LineObj bLine(x0, y0, x2, y2);
  274.     LineObj rLine(x2, y2, x3, y3);
  275.     LineObj tLine(x1, y1, x3, y3);
  276.  
  277.     gs->SetBrush(border);
  278.     update(gs);
  279.     if (clipBox.Intersects(lLine)) {
  280.     pLine(c, 0, 0, 0, pgheight);
  281.     }
  282.     if (clipBox.Intersects(bLine)) {
  283.     pLine(c, 0, 0, pgwidth, 0);
  284.     }
  285.     if (clipBox.Intersects(rLine)) {
  286.     pLine(c, pgwidth, 0, pgwidth, pgheight);
  287.     }
  288.     if (clipBox.Intersects(tLine)) {
  289.     pLine(c, 0, pgheight, pgwidth, pgheight);
  290.     }
  291. }
  292.  
  293. // DefinePoints defines just enough points to grid the given area.
  294.  
  295. int Page::DefinePoints (Coord l, Coord b, Coord r, Coord t, Graphic* gs) {
  296.     float x0, y0, x1, y1;
  297.     invTransformRect(float(l),float(b),float(r),float(t), x0, y0, x1, y1, gs);
  298.     x0 = round(x0/spacing_pixels) * spacing_pixels;
  299.     y0 = round(y0/spacing_pixels) * spacing_pixels;
  300.     x0 = max((float)0.0, x0);
  301.     y0 = max((float)0.0, y0);
  302.     x1 = min(x1, (float)pagewidth);
  303.     y1 = min(y1, (float)pageheight);
  304.     int x_count = int((x1 - x0)/spacing_pixels) + 1;
  305.     int y_count = int((y1 - y0)/spacing_pixels) + 1;
  306.     int count = x_count * y_count;
  307.  
  308.     for (int i = 0; i < x_count; i++) {
  309.     Coord ix = round(x0 + i*spacing_pixels);
  310.     for (int j = i; j < count; j += x_count) {
  311.         x[j] = ix;
  312.     }
  313.     }
  314.  
  315.     for (i = 0; i < y_count; i++) {
  316.     Coord iy = round(y0 + i*spacing_pixels);
  317.     for (int j = i * x_count; j < (i+1) * x_count; j++) {
  318.         y[j] = iy;
  319.     }
  320.     }
  321.  
  322.     return count;
  323. }
  324.